import { Link, useSearchParams } from "react-router-dom";
import {
  Card,
  Breadcrumb,
  Form,
  Button,
  Radio,
  Input,
  Upload,
  Space,
  Select,
  message,
} from "antd";
import { PlusOutlined } from "@ant-design/icons";
import ReactQuill from 'react-quill'
import type { UploadProps, UploadFile, RadioProps, RadioChangeEvent, FormProps } from "antd"; 
import type { UploadChangeParam } from "antd/es/upload";
import { useChannel } from "@/hooks/useChannel";
import { createArticleApi, getArticleByIdApi, updateArticleApi } from "@/apis/article";
import 'react-quill/dist/quill.snow.css'
import StyledPublish from "./index.css";


enum CoverTypes {
  One = 1,
  Three = 3,
  Zero = 0
}
const { Option } = Select;

const Publish = () => {
  const channelList = useChannel();  // 获取频道数据

  const [searchParams] = useSearchParams()
  const articleId = searchParams.get('id') // 获取跳转过来的路由参数id
  const [form] = Form.useForm() // 获取表单

  // 用于路由携带文章id跳转回来后来进行数据获取和回填的
  useEffect(() => { 
    async function getArticle () {
      const res = await getArticleByIdApi(articleId as string)
      const { cover, ...formValue } = res.data
      // 设置表单数据
      form.setFieldsValue({ ...formValue, type: cover.type })
      // 2. 回填封面图片
      setCoverType(cover.type) // 封面类型
      setCoverList(cover.images.map((url: string) => ({ url }))) // 封面list
    }
    if (articleId) {
      // 拉取数据回显
      getArticle()
    }
  }, [articleId, form])
  
  // 上传封面图片的回调
  const [coverList, setCoverList] = useState<UploadFile[]>([])
  const onUploadChange: UploadProps['onChange'] = useCallback(
    (uploadInfo: UploadChangeParam<UploadFile<any>>) => {
      setCoverList(uploadInfo.fileList)
    }, []
  );

  // 封面类型改变的回调
  const [coverType, setCoverType] = useState<CoverTypes>(CoverTypes.One)
  const onCoverTypeChange: RadioProps['onChange'] = useCallback((e: RadioChangeEvent) => {
    const type = e.target.value! as CoverTypes
    setCoverType(type)  
    setCoverList(coverList.slice(0, type)) // 类型改变时将图片列表数量修改和类型一致
  }, [coverList])

  // 上传文章数据
  const onFinish: FormProps['onFinish'] = useCallback(async (form: { 
    title: string, channel_id: number, content: string 
  }) => {
    // 由于上传图片的数据格式和从后端获取的图片的数据格式不一致，需要做转换处理
    const formatUrl = (list: UploadFile[]) => { 
      return list.map(item => {
        if (item.response) {
          return item.response.data.url
        } else {
          return item.url
        }
      })
    }
    if(coverList.length !== coverType) {
      return message.warning("封面类型和图片选择数量不符")
    }
    const { title, channel_id, content } = form
    try{
      const data = {
        title, channel_id, content,
        cover: {
          type: coverType,
          images: formatUrl(coverList)
        }
      };
      if(articleId){
        await updateArticleApi(articleId, data)
      }
      else {
        await createArticleApi(data);
      }
      message.success(`${articleId ? '编辑' : '发布'}文章成功`)
    }catch(e){
      return Promise.reject(e)
    }
  }, [coverList, coverType, articleId])

  return (
    <StyledPublish>
      <div className="publish">
        <Card
          title={
            <Breadcrumb
              items={[
                { title: <Link to={"/"}>首页</Link> },
                { title: `${articleId ? '编辑文章' : '发布文章'}` },
              ]}
            />
          }
        >
          <Form
            form={form}
            labelCol={{ span: 4 }}
            wrapperCol={{ span: 16 }}
            initialValues={{ type: coverType }}
            onFinish={onFinish}
          >
            <Form.Item
              name="title"
              label="标题"
              rules={[{ required: true, message: "请输入文章标题" }]}
            >
              <Input placeholder="请输入文章标题" style={{ width: 400 }} />
            </Form.Item>
            <Form.Item
              name="channel_id"
              label="频道"
              rules={[{ required: true, message: "请选择文章频道" }]}
            >
              <Select placeholder="请选择文章频道" style={{ width: 400 }}>
                {/* value属性会作为接口的提交字段 */}
                {
                  channelList.map((channel) => (
                    <Option key={channel.id} value={channel.id}>{channel.name}</Option>
                  ))
                }
              </Select>
            </Form.Item>
            <Form.Item label="封面">
              <Form.Item name="type">
                <Radio.Group onChange={onCoverTypeChange}>
                  <Radio value={CoverTypes.One}>单图</Radio>
                  <Radio value={CoverTypes.Three}>三图</Radio>
                  <Radio value={CoverTypes.Zero}>无图</Radio>
                </Radio.Group>
              </Form.Item>
              {/* listType决定选择框的样式，showUploadList控制显示上传列表 */}
              {
                coverType > 0 &&
                  <Upload              
                    listType="picture-card"              
                    showUploadList
                    action={'http://geek.itheima.net/v1_0/upload'}
                    name="image"
                    onChange={onUploadChange}
                    maxCount={coverType}
                    fileList={coverList}
                    // 需要加入fileList属性来显示获取的url属性
                  >
                    <div style={{ marginTop: 8 }}>
                      <PlusOutlined />
                    </div>
                  </Upload>
              }
            </Form.Item>
            <Form.Item
              name="content"
              label="内容"
              rules={[{ required: true, message: "请输入文章内容" }]}
            >
              <ReactQuill
                className="publish-quill"
                theme="snow"
                placeholder="请输入文章内容"
              />
            </Form.Item>
            <Form.Item wrapperCol={{ offset: 4 }}>
              <Space>
                <Button size="large" type="primary" htmlType="submit">
                  { articleId ? '更新文章' : '发布文章'}
                </Button>
              </Space>
            </Form.Item>
          </Form>
        </Card>
      </div>
    </StyledPublish>
  );
};

export default Publish;
